home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-11-04 | 57.2 KB | 2,505 lines |
- Newsgroups: comp.sources.misc
- From: briana@tau-ceti.isc-br.com (Brian W. Antoine)
- Subject: v25i019: st01scsi - DOS SCSI Driver for the Seagate ST-01, v2.0, Part02/02
- Message-ID: <1991Nov5.033452.4414@sparky.imd.sterling.com>
- X-Md4-Signature: db7f3dda25e39475703534e67a7028f3
- Date: Tue, 5 Nov 1991 03:34:52 GMT
- Approved: kent@sparky.imd.sterling.com
-
- Submitted-by: briana@tau-ceti.isc-br.com (Brian W. Antoine)
- Posting-number: Volume 25, Issue 19
- Archive-name: st01scsi/part02
- Environment: DOS, ST-01
- Supersedes: ST01SCSI.12: Volume 15, Issue 2-3
-
- #
- # This is a Shell Archive.
- # Remove everything above and including the cut line.
- # Then run the rest of the file through #! /bin/sh.
- # -----cut here-----cut here-----cut here-----cut here-----
- #! /bin/sh
- # Execute the file with #! /bin/sh (not csh) to create the files:
- # dump.asm
- # ioctl.asm
- # kludge.asm
- # scsi.asm
- # subs.asm
- # units.asm
- # This Archive created: Fri Oct 18 22:46:09 1991
- # By: Brian W. Antoine at ISC - Bunker Ramo, Spokane, WA
- #
- export PATH; PATH=/bin:$PATH
- echo shar: extracting "'dump.asm'" '(1362 characters)'
- if test -f 'dump.asm'
- then
- echo shar: will not over-write existing file "'dump.asm'"
- else
- sed 's/^XX//' > 'dump.asm' << \SHAR_EOF
- XX;
- XX; Convert bin (ax) to ascii (bx => buffer)
- XX;
- XXbin_ascii proc near
- XX pusha
- XX push ax
- XX mov cx,6
- XXfill_buff: mov byte ptr [bx],' '
- XX inc bx
- XX loop fill_buff
- XX mov si,10
- XX or ax,ax
- XX jns clr_dvd
- XX neg ax
- XXclr_dvd: sub dx,dx
- XX div si
- XX add dx,'0'
- XX dec bx
- XX mov [bx],dl
- XX inc cx
- XX or ax,ax
- XX jnz clr_dvd
- XX pop ax
- XX or ax,ax
- XX jns no_more
- XX dec bx
- XX mov byte ptr [bx],'-'
- XXno_more: popa
- XX ret
- XXbin_ascii endp
- XX
- XX;
- XX; Convert Hex (dx) to Ascii (bx => buffer)
- XX;
- XXhex2asc4 proc near
- XX push cx
- XX push ax
- XX mov cx,4 ;Do Four Digits
- XXh241: rol dx,1
- XX rol dx,1
- XX rol dx,1
- XX rol dx,1
- XX mov al,dl ;Get the Current Digit
- XX and al,0Fh
- XX cmp al,0Ah ;Is It Hex?
- XX jge h242
- XX add al,30h ;Normal Digit
- XX jmp h243
- XXh242: add al,37h ;Hex Digit
- XXh243: mov [bx],al ;Insert in Buffer
- XX inc bx
- XX loop h241
- XX pop ax
- XX pop cx
- XX ret
- XXhex2asc4 endp
- XX
- XX;
- XX; Convert Hex (dl) to Ascii (bx => buffer)
- XX;
- XXhex2asc2 proc near
- XX push cx
- XX push ax
- XX mov cx,2 ;Do Two Digits
- XXh221: rol dl,1
- XX rol dl,1
- XX rol dl,1
- XX rol dl,1
- XX mov al,dl ;Get the Current Digit
- XX and al,0Fh
- XX cmp al,0Ah ;Is It Hex?
- XX jge h222
- XX add al,30h ;Normal Digit
- XX jmp h223
- XXh222: add al,37h ;Hex Digit
- XXh223: mov [bx],al ;Insert in Buffer
- XX inc bx
- XX loop h221
- XX pop ax
- XX pop cx
- XX ret
- XXhex2asc2 endp
- XX
- XX;
- XX; Print a string
- XX;
- XX; ds:dx => string
- XX;
- XXputs proc near
- XX pusha
- XX mov ah,9 ;DOS print string
- XX int 21h
- XX popa
- XX ret
- XXputs endp
- SHAR_EOF
- if test 1362 -ne "`wc -c < 'dump.asm'`"
- then
- echo shar: error transmitting "'dump.asm'" '(should have been 1362 characters)'
- fi
- fi # end of overwriting check
- echo shar: extracting "'ioctl.asm'" '(5778 characters)'
- if test -f 'ioctl.asm'
- then
- echo shar: will not over-write existing file "'ioctl.asm'"
- else
- sed 's/^XX//' > 'ioctl.asm' << \SHAR_EOF
- XX;
- XX; Process an ioctl request for the current unit
- XX;
- XX; return 'C' on error
- XX;
- XXscsi_ioctl proc
- XX mov al,es:[bx].rh19_minor ;Get the minor number
- XX cmp al,40h ;Set Device Params?
- XX jnz scsi_i_42h
- XX clc
- XX jmp scsi_i_exit
- XX
- XXscsi_i_42h: cmp al,42h ;Format and Verify?
- XX jnz scsi_i_60h
- XX mov di,es:[bx].rh19_buf_ofs ;Get the Param Buffer
- XX mov ax,es:[bx].rh19_buf_seg
- XX mov es,ax
- XX mov ax,es:[di].ioctl_fmt_cyl ;Cylinder
- XX mov bx,SECT_TRACK
- XX mul bx ;Convert to Sector
- XX mov cx,es:[di].ioctl_fmt_head ;Head
- XX or cx,cx
- XX jz head0_42h
- XXhead_loop_42h: add ax,SECT_TRACK ;Add Head Tracks
- XX adc dx,0
- XX loop head_loop_42h
- XXhead0_42h: mov bx,0
- XX mov cx,es:[di].ioctl_fmt_len ;How Many Tracks
- XXlen_loop_42h: add bx,SECT_TRACK ;Convert to Sectors
- XX loop len_loop_42h
- XX mov cx,bx
- XX
- XX ife large_drives
- XX mov di,cur_bpb ;Add Drive Offset
- XX mov dx,[di].bpb_hs_msw
- XX endif
- XX
- XX call scsi_verify
- XX jmp scsi_i_exit
- XX
- XXscsi_i_60h: cmp al,60h ;Get Device Params?
- XX jnz scsi_i_61h
- XXbuild_bpb: mov si,cur_bpb ;Get the Current BPB
- XX mov di,es:[bx].rh19_buf_ofs ;Get the Param Buffer
- XX mov ax,es:[bx].rh19_buf_seg
- XX mov es,ax
- XX mov es:[di].dpb_special,05h ;Sect Same/Use Cur BPB
- XX mov es:[di].dpb_type,05h ;Fixed Disk
- XX mov es:[di].dpb_attr,0001h ;Not Removable
- XX if large_drives
- XX mov dx,[si].bpb_ts_msw
- XX mov ax,[si].bpb_ts_lsw
- XX else
- XX mov dx,0
- XX mov ax,[si].bpb_ts
- XX endif
- XX add ax,1 ;Sectors (1-n)
- XX adc dx,0
- XX mov bx,SECT_TRACK
- XX div bx
- XX mov es:[di].dpb_cyl,ax
- XX mov es:[di].dpb_media,0 ;????
- XX mov es:[di].dpb_sectors,SECT_TRACK ;Sectors per Track
- XX
- XX push di
- XX lea di,es:[di].dpb_bpb ;Copy the bpb into
- XX mov cx,size bpb ;the requestors buffer
- XX cld
- XX rep movsb
- XX pop di
- XX
- XX lea di,es:[di].dpb_track ;Build the Track List
- XX mov cx,SECT_TRACK
- XX mov ax,0 ;Start with Sector 0
- XXscsi_i_t_loop: mov es:[di],ax ;Sector Number
- XX inc ax
- XX inc di
- XX inc di
- XX mov word ptr es:[di],P_SECT ;Sector Size
- XX inc di
- XX inc di
- XX loop scsi_i_t_loop
- XX clc
- XX jmp short scsi_i_exit
- XX
- XXscsi_i_61h: cmp al,61h ;Read Track?
- XX jnz scsi_i_62h
- XX mov di,es:[bx].rh19_buf_ofs ;Get the Param Buffer
- XX mov ax,es:[bx].rh19_buf_seg
- XX mov es,ax
- XX mov ax,es:[di].ioctl_read_cyl ;Cylinder
- XX mov bx,SECT_TRACK
- XX mul bx ;Convert to Sector
- XX mov cx,es:[di].ioctl_read_head ;Head
- XX or cx,cx
- XX jz head0_61h
- XXhead_loop_61h: add ax,SECT_TRACK ;Add Head Tracks
- XX adc dx,0
- XX loop head_loop_61h
- XXhead0_61h: add ax,es:[di].ioctl_read_sect ;Offset into the Track
- XX adc dx,0
- XX mov cx,es:[di].ioctl_read_len ;How Many Sectors
- XX
- XX ife large_drives
- XX mov di,cur_bpb ;Add Drive Offset
- XX mov dx,[di].bpb_hs_msw
- XX endif
- XX
- XX call scsi_verify
- XX jc scsi_i_error
- XX mov es,rh_seg
- XX mov bx,rh_off
- XX jmp build_bpb
- XX
- XXscsi_i_62h: cmp al,62h ;Verify?
- XX jnz scsi_i_error
- XX mov di,es:[bx].rh19_buf_ofs ;Get the Param Buffer
- XX mov ax,es:[bx].rh19_buf_seg
- XX mov es,ax
- XX mov ax,es:[di].ioctl_fmt_cyl ;Cylinder
- XX mov bx,SECT_TRACK
- XX mul bx ;Convert to Sector
- XX mov cx,es:[di].ioctl_fmt_head ;Head
- XX or cx,cx
- XX jz head0_62h
- XXhead_loop_62h: add ax,SECT_TRACK ;Add Head Tracks
- XX adc dx,0
- XX loop head_loop_62h
- XXhead0_62h: mov bx,0
- XX mov cx,es:[di].ioctl_fmt_len ;How Many Tracks
- XXlen_loop_62h: add bx,SECT_TRACK ;Convert to Sectors
- XX loop len_loop_62h
- XX mov cx,bx
- XX
- XX ife large_drives
- XX mov di,cur_bpb ;Add Drive Offset
- XX mov dx,[di].bpb_hs_msw
- XX endif
- XX
- XX call scsi_verify
- XX jmp short scsi_i_exit
- XX
- XXscsi_i_error: stc
- XXscsi_i_exit: ret
- XXscsi_ioctl endp
- XX
- XX;
- XX; Process an ioctl_write request
- XX;
- XXscsi_ioctl_write proc
- XX mov di,es:[bx].rh12_buf_ofs ;Get The Command
- XX mov ax,es:[bx].rh12_buf_seg ;Buffer
- XX mov es,ax
- XX mov ax,es:[di].ioc_command ;What Command
- XX
- XX;
- XX; Format Disk Unit
- XX;
- XX cmp al,'F' ;Format?
- XX jnz try_erase
- XX mov ax,es:[di].ioc_param1 ;Get Interleave
- XX mov bx,es:[di].ioc_buf_ofs ;Get Buffer Offset
- XX mov cx,es:[di].ioc_buf_len ;Get Buffer Length
- XX mov dx,es:[di].ioc_param2 ;Get Format Type
- XX mov es,es:[di].ioc_buf_seg ;Get Buffer Seg
- XX lea di,cmd_format ;Insert into Command
- XX mov [di].fmt_cmd_il_b1,ah
- XX mov [di].fmt_cmd_il_b0,al
- XX mov [di].fmt_cmd_type,dl
- XX call docmd
- XX jnc format_exit
- XX call scsi_sense
- XXformat_exit: jmp scsi_i_w_exit
- XX
- XX;
- XX; Erase Tape Unit
- XX;
- XXtry_erase: cmp al,'E' ;Erase?
- XX jnz try_rewind
- XX lea di,cmd_erase ;Now Erase Tape
- XX call docmd
- XX jnc erase_exit
- XX call scsi_sense
- XXerase_exit: jmp scsi_i_w_exit
- XX
- XX;
- XX; Rewind Tape Unit
- XX;
- XXtry_rewind: cmp al,'R' ;Rewind?
- XX jnz try_load
- XX lea di,cmd_rewind ;Now Rewind Tape
- XX call docmd
- XX jnc rewind_exit
- XX call scsi_sense
- XXrewind_exit: jmp scsi_i_w_exit
- XX
- XX;
- XX; Load Tape on Open
- XX;
- XXtry_load: cmp al,'L' ;Load?
- XX jnz try_noload
- XX mov load_flag,TRUE
- XX jmp scsi_i_w_exit
- XX
- XX;
- XX; No Load Tape on Open
- XX;
- XXtry_noload: cmp al,'N' ;No Load?
- XX jnz try_space
- XX mov load_flag,FALSE
- XX jmp scsi_i_w_exit
- XX
- XX;
- XX; Space Tape
- XX;
- XXtry_space: cmp al,'S' ;Space?
- XX jnz try_filemark
- XX mov ax,es:[di].ioc_param1 ;Get Count
- XX mov bx,es:[di].ioc_param2 ;Get Type
- XX lea di,cmd_space ;Insert into Command
- XX mov [di].space_cmd_code,bl
- XX mov [di].space_cmd_cnt2,ah ;Dup of ah
- XX mov [di].space_cmd_cnt1,ah
- XX mov [di].space_cmd_cnt0,al
- XX call docmd
- XX jnc scsi_i_w_exit
- XX call scsi_sense
- XX jmp scsi_i_w_exit
- XX
- XX;
- XX; Write Filemarks
- XX;
- XXtry_filemark: cmp al,'M' ;Mark?
- XX jnz try_remap
- XX mov ax,es:[di].ioc_param1 ;Get Count
- XX lea di,cmd_twritefm ;Insert into Command
- XX mov [di].fm_cmd_cnt_b1,ah
- XX mov [di].fm_cmd_cnt_b0,al
- XX call docmd
- XX jnc scsi_i_w_exit
- XX call scsi_sense
- XX jmp scsi_i_w_exit
- XX
- XX;
- XX; Reassign Block
- XX;
- XXtry_remap: cmp al,'A' ;ReAssign?
- XX jnz scsi_i_w_error
- XX mov bx,es:[di].ioc_buf_ofs ;Get Buffer Offset
- XX mov cx,es:[di].ioc_buf_len ;Get Buffer Length
- XX mov es,es:[di].ioc_buf_seg ;Get Buffer Seg
- XX lea di,cmd_remap ;Command
- XX call docmd
- XX jnc scsi_i_w_exit
- XX call scsi_sense
- XX jmp scsi_i_w_exit
- XX
- XXscsi_i_w_error: stc
- XXscsi_i_w_exit: ret
- XXscsi_ioctl_write endp
- SHAR_EOF
- if test 5778 -ne "`wc -c < 'ioctl.asm'`"
- then
- echo shar: error transmitting "'ioctl.asm'" '(should have been 5778 characters)'
- fi
- fi # end of overwriting check
- echo shar: extracting "'kludge.asm'" '(2417 characters)'
- if test -f 'kludge.asm'
- then
- echo shar: will not over-write existing file "'kludge.asm'"
- else
- sed 's/^XX//' > 'kludge.asm' << \SHAR_EOF
- XX;
- XX; This code is needed because DOS insists on opening a char device
- XX; in cooked mode. The problem is that without adding code to every
- XX; application that would ever use us, we have no way to alter this
- XX; because the use of O_BINARY or setmode() do not affect char devices.
- XX;
- XX; The solution (kludge) is to watch open requests issued thru the
- XX; INT 21 vector. If we see a open request followed by a OPEN_DEV
- XX; call to us, it must have been an open for us. So during the return,
- XX; force a call to the ioctl facility that will switch to raw mode.
- XX;
- XX
- XX;
- XX; The Original INT 21 Vector
- XX;
- XXvect_int_21 equ word ptr 4 * 21h
- XXorig_int_21 dd ? ;Original INT 21 Vector
- XX
- XX;
- XX; OPEN_DEV flag is TRUE when we are opened
- XX;
- XXopened_flag db FALSE
- XX
- XXpatch_us_in proc near
- XX push es
- XX push ax
- XX mov ax,0 ;Patch Ourselves into
- XX mov es,ax ;the INT 21 Vector
- XX mov ax,es:[vect_int_21] ;Offset
- XX mov word ptr orig_int_21,ax
- XX lea ax,our_int_21
- XX mov es:[vect_int_21],ax
- XX mov ax,es:[vect_int_21+2] ;Segment
- XX mov word ptr orig_int_21+2,ax
- XX mov ax,cs
- XX mov es:[vect_int_21+2],ax
- XX pop ax
- XX pop es
- XX ret
- XXpatch_us_in endp
- XX
- XXour_int_21 proc far
- XX pushf ;Save entry flags
- XX cmp ah,3Dh ;Is it an open request?
- XX jnz not_open_req
- XX popf ;Restore entry flags
- XX;
- XX; We need to set things up so the 'iret' done by the INT 21
- XX; code will have some the right stuff on the stack.
- XX; #1 Flags with interrupts enabled
- XX; #2 Return Address
- XX;
- XX sti ;Allow interrupts
- XX pushf ;After the iret
- XX cli ;Shut interrupts off
- XX call cs:orig_int_21 ;While we Pass the request on
- XX;
- XX; Upon return, interrupts are enabled, so shut them off while we work
- XX;
- XX pushf
- XX cli
- XX cmp cs:opened_flag,FALSE ;Was it an open for us?
- XX jz not_our_open
- XX mov cs:opened_flag,FALSE ;Clear for next time
- XX;
- XX; We need to forge a call to the ioctl interface
- XX; to switch DOS to raw mode when it talks to us
- XX;
- XX pusha
- XX mov bx,ax ;Save the Handle
- XX mov ax,4400h ;Get Device Information
- XX pushf
- XX call cs:orig_int_21
- XX mov dh,0 ;Setup
- XX or dl,20h ;for RAW Mode
- XX mov ax,4401h ;Set Device Information
- XX pushf
- XX call cs:orig_int_21
- XX popa
- XX
- XXnot_our_open: popf ;The Original Flags to return
- XX;
- XX; When we return, we need to pop the flags that the original INT 21
- XX; call left on the stack, and return the flags we got back
- XX;
- XX ret 2 ;Return and discard flags
- XX
- XXnot_open_req: popf ;Pop the saved flags
- XX jmp cs:orig_int_21 ;Continue with original code
- XXour_int_21 endp
- SHAR_EOF
- if test 2417 -ne "`wc -c < 'kludge.asm'`"
- then
- echo shar: error transmitting "'kludge.asm'" '(should have been 2417 characters)'
- fi
- fi # end of overwriting check
- echo shar: extracting "'scsi.asm'" '(14291 characters)'
- if test -f 'scsi.asm'
- then
- echo shar: will not over-write existing file "'scsi.asm'"
- else
- sed 's/^XX//' > 'scsi.asm' << \SHAR_EOF
- XX;
- XX; Simple SCSI Device Driver
- XX;
- XX PAGE 76,132
- XX
- XX INCLUDE options.inc
- XX INCLUDE equ.inc
- XX INCLUDE struct.inc
- XX
- XX ife oldcode
- XX .286
- XX else
- XX .8086
- XXpusha macro
- XX push ax
- XX push bx
- XX push cx
- XX push dx
- XX push si
- XX push di
- XX endm
- XX
- XXpopa macro
- XX pop di
- XX pop si
- XX pop dx
- XX pop cx
- XX pop bx
- XX pop ax
- XX endm
- XX endif
- XX
- XX;
- XX; Start of Code and Data
- XX;
- XX_TEXT segment word public 'CODE'
- XX assume cs:_TEXT, ds:_TEXT, es:_TEXT
- XX
- XX org 0
- XX
- XX;
- XX; Device Header Required By DOS
- XX;
- XXscsi:
- XXtape_link_ofs dw disk_link_ofs ;Forward Link
- XXtape_link_seg dw -1
- XX dw 0C800h ;Char Device
- XX dw tape_strategy ;Address of 1st DOS Call
- XX dw dev_interrupt ;Address of 2nd DOS Call
- XX db 'SCSITAPE' ;Device Name
- XX
- XXdisk_link_ofs dw -1 ;Forward Link
- XXdisk_link_seg dw -1
- XX if large_drives
- XX dw 06042h ;Ioctl R/W, Block Device, Non-IBM, Get/Set, 32 bit
- XX else
- XX dw 06040h ;Ioctl R/W, Block Device, Non-IBM, Get/Set
- XX endif
- XX dw disk_strategy ;Address of 1st DOS Call
- XX dw dev_interrupt ;Address of 2nd DOS Call
- XXdisk_count db 0 ;Number of Disks Present
- XX db 7 dup(?)
- XX
- XX;
- XX; Work Space For Our Device Driver
- XX;
- XX even
- XXrh_off dw ? ;Request Header Offset
- XXrh_seg dw ? ;Request Header Segment
- XXrh_type db ? ;Request Type
- XX
- XXwrite_flag db FALSE ;TRUE When Tape Write Seen
- XXread_flag db FALSE ;TRUE When Tape Read Seen
- XXerror_flag db FALSE ;TRUE When Tape Error Seen
- XXload_flag db TRUE ;TRUE When Tape should Load/Unload
- XXcur_drive db -1
- XXvol_id db 'NO NAME ',0
- XX
- XX;
- XX; The Original INT 24 Vector
- XX;
- XXvect_int_24 equ word ptr 4 * 24h
- XXorig_int_24 dd ? ;Original INT 24 Vector
- XX
- XX;
- XX; Define our own personal Stack
- XX;
- XX even
- XXnew_stack db STACK_SIZE-2 dup (?) ;Our Local Stack
- XXnew_stack_top dw ?
- XX
- XXstack_ptr dw ? ;Old Stack Pointer
- XXstack_seg dw ? ;Old Stack Segment
- XX
- XX;
- XX; Command Table
- XX;
- XXcmdtab label byte ;* = Char Only Devices
- XX dw INITIALIZATION ;Initialization
- XX dw MEDIA_CHECK ;Media Check (Block Only)
- XX dw GET_BPB ;Build BPB (Block Only)
- XX dw unknown ;IOCTL Read
- XX dw READ ;Read Data
- XX dw done ;*Non Destructive Read
- XX dw done ;*Read Status
- XX dw done ;*Flush Read Buffer
- XX dw WRITE ;Write Data
- XX dw WRITE_VERIFY ;Write With Verify
- XX dw done ;*Write Status
- XX dw done ;*Flush Write Buffer
- XX dw WRITE_IOCTL ;IOCTL Write
- XX dw OPEN_DEV ;Device Open
- XX dw CLOSE_DEV ;Device Close
- XX dw done ;Removable Check
- XX dw unknown ;*Write Until Busy
- XX dw unknown ;Unknown Call
- XX dw unknown ;Unknown Call
- XX dw IOCTL ;Generic Ioctl
- XX dw unknown ;Unknown Call
- XX dw unknown ;Unknown Call
- XX dw unknown ;Unknown Call
- XX dw GET_DEV ;Get Device
- XX dw SET_DEV ;Set Device
- XX
- XX;
- XX; Int 24 (Fatal Error Handler)
- XX;
- XX; The test for our tape device only works because the
- XX; device header for the tape is located at the start
- XX; of the driver binary.
- XX;
- XXour_int_24 proc far
- XX push ax
- XX mov ax,cs ;Is it our Segment
- XX cmp bp,ax
- XX jnz not_our_tape
- XX cmp si,0 ;Is it the Tape Device
- XX jnz not_our_tape
- XX pop ax
- XX mov al,3 ;Fail the System Call
- XX iret
- XXnot_our_tape: pop ax
- XX jmp cs:orig_int_24 ;Pass the Request On
- XXour_int_24 endp
- XX
- XX;
- XX; Strategy Procedure
- XX;
- XXdisk_strategy proc far
- XX mov cs:rh_seg,es ;Save Request Header Ptr Segment
- XX mov cs:rh_off,bx ;Save Request Header Ptr Offset
- XX mov cs:rh_type,DISK_REQUEST
- XX ret
- XXdisk_strategy endp
- XX
- XXtape_strategy proc far
- XX mov cs:rh_seg,es ;Save Request Header Ptr Segment
- XX mov cs:rh_off,bx ;Save Request Header Ptr Offset
- XX mov cs:rh_type,TAPE_REQUEST
- XX ret
- XXtape_strategy endp
- XX
- XX;
- XX; Interrupt Procedure
- XX;
- XXdev_interrupt proc far
- XX pushf ;Save Machine State On Entry
- XX cli
- XX push ds
- XX push es
- XX push ax
- XX push bx
- XX push cx
- XX push dx
- XX push si
- XX push di
- XX push bp
- XX
- XX mov cs:stack_seg,ss ;Save Old Stack
- XX mov cs:stack_ptr,sp
- XX
- XX mov ax,cs ;Save us the Segment Override Crap
- XX mov ds,ax
- XX mov es,ax
- XX
- XX mov ss,ax ;Setup Our Local Stack
- XX lea ax,new_stack_top
- XX mov sp,ax
- XX sti ;We're Safe Now
- XX
- XX;
- XX; Perform branch based on the command passed in the Request Header
- XX;
- XX mov es,rh_seg ;Point us at the Request Header
- XX mov bx,rh_off
- XX
- XX mov al,es:[bx].rh_cmd ;Get Command Code
- XX rol al,1 ;Get offset into table
- XX lea di,cmdtab ;Get address of command table
- XX mov ah,0 ;Clear hi order byte
- XX add di,ax ;Add offset
- XX jmp word ptr [di] ;Jump Indirect
- XX
- XX;
- XX; Command Procedures
- XX;
- XXINITIALIZATION: cmp rh_type,TAPE_REQUEST ;Is this SCSITAPE: Init?
- XX jz init_skip
- XX mov al,es:[bx].rh0_drv_ltr ;Save the starting Drive
- XX add al,041h
- XX mov cur_drive,al
- XX call initial ;Setup
- XX if use_kludge
- XX call patch_us_in
- XX endif
- XX mov bx,rh_off
- XX mov es,rh_seg
- XXinit_skip: lea ax,initial ;Set The Break Address
- XX mov es:[bx].rh0_brk_ofs,ax
- XX mov es:[bx].rh0_brk_seg,cs
- XX mov al,disk_count ;Number of Disk Devices Supported
- XX mov es:[bx].rh0_nunits,al
- XX lea dx,bpb_array ;BPB Array
- XX mov es:[bx].rh0_bpb_tbo,dx
- XX mov es:[bx].rh0_bpb_tbs,cs
- XX jmp done
- XX
- XX;
- XX; Has the Media Changed
- XX;
- XXMEDIA_CHECK: call find_unit
- XX jc mc_jmp_err
- XX mov di,cur_unit
- XX mov al,[di].unit_mcheck ;Get Initial Status
- XX mov [di].unit_mcheck,1 ;Always OK from then on
- XX mov es:[bx].rh1_md_stat,al
- XX lea dx,vol_id ;Address of Volume ID
- XX mov es:[bx].rh1_volid_ofs,dx
- XX mov es:[bx].rh1_volid_seg,cs
- XX jmp done
- XXmc_jmp_err: jmp bad_unit
- XX
- XX;
- XX; Get Disk Parameter Block
- XX;
- XXGET_BPB: call find_unit
- XX jc get_jmp_err
- XX mov dx,cur_bpb ;Address of BPB
- XX mov es:[bx].rh2_pbpbo,dx
- XX mov es:[bx].rh2_pbpbs,cs
- XX jmp done
- XXget_jmp_err: jmp bad_unit
- XX
- XX;
- XX; Read some data from the disk/tape
- XX;
- XXREAD: cmp rh_type,DISK_REQUEST
- XX jz read_a_disk
- XX mov ax,tape_unit ;Do We Have a Tape?
- XX cmp ax,-1
- XX jz read_jmp_err1
- XX mov cur_unit,ax
- XX call tape_read
- XX jc read_jmp_err2
- XX jmp done
- XXread_a_disk: call find_unit
- XX jc read_jmp_err1
- XX call disk_read
- XX jc read_jmp_err2
- XX jmp done
- XXread_jmp_err1: jmp bad_unit
- XXread_jmp_err2: jmp bad_read
- XX
- XX;
- XX; Write some data to the disk/tape
- XX;
- XXWRITE equ $
- XXWRITE_VERIFY: cmp rh_type,DISK_REQUEST
- XX jz write_a_disk
- XX mov ax,tape_unit ;Do We Have a Tape?
- XX cmp ax,-1
- XX jz write_jmp_err1
- XX mov cur_unit,ax
- XX call tape_write
- XX jc write_jmp_err2
- XX jmp done
- XXwrite_a_disk: call find_unit
- XX jc write_jmp_err1
- XX call disk_write
- XX jc write_jmp_err2
- XX jmp done
- XXwrite_jmp_err1: jmp bad_unit
- XXwrite_jmp_err2: jmp bad_write
- XXwrite_jmp_err3: jmp unknown
- XX
- XX;
- XX; Write Ioctl Packet
- XX;
- XXWRITE_IOCTL: cmp rh_type,DISK_REQUEST
- XX jz ioctl_a_disk
- XX mov ax,tape_unit ;Do we have a SCSITAPE?
- XX cmp ax,-1
- XX jz write_jmp_err1
- XX mov cur_unit,ax
- XX jmp short ioctl_do
- XXioctl_a_disk: call find_unit
- XX jc write_jmp_err1
- XXioctl_do: call scsi_ioctl_write
- XX jc write_jmp_err3
- XX jmp done
- XX
- XX;
- XX; Special Control Functions
- XX;
- XXIOCTL: call find_unit
- XX jc ioctl_jmp_err1
- XX call scsi_ioctl
- XX jc ioctl_jmp_err2 ;Must have been a Verify error
- XX jmp done
- XXioctl_jmp_err1: jmp bad_unit
- XXioctl_jmp_err2: jmp bad_read
- XX
- XX;
- XX; Open Tape Device
- XX;
- XXOPEN_DEV: mov di,tape_unit
- XX cmp di,-1 ;Do We have a SCSITAPE: Unit?
- XX jnz open_tape
- XX jmp bad_unit
- XXopen_tape: mov cur_unit,di ;New Current Unit
- XX lea bx,[di].unit_sense ;Buffer Offset
- XX push ds ;Buffer Segment
- XX pop es
- XX mov cx,size sense ;Buffer Size
- XX lea di,cmd_sense ;Command
- XX call docmd
- XX jc open_err
- XX cmp load_flag,TRUE ;Should we LOAD?
- XX jnz open_ok
- XX ife mini_inquire
- XX mov di,cur_unit ;Check Unit Type
- XX mov ax,word ptr [di].unit_inq_buf.inq_manufact
- XX lea di,cmd_rewind ;Default to Rewind
- XX cmp ax,'ET' ;If this is a TEAC Unit
- XX jz open_rewind
- XX endif
- XX lea di,cmd_load ;Now Load Tape
- XX mov [di].load_cmd_type,LOAD_TAPE
- XXopen_rewind: call docmd
- XX jnc open_ok
- XX call scsi_sense
- XXopen_err: jmp general
- XXopen_ok: mov write_flag,FALSE ;No Writes Seen
- XX mov read_flag,FALSE ;No Reads Seen
- XX mov error_flag,FALSE ;No Error Yet
- XX if use_kludge
- XX mov opened_flag,TRUE ;We are Open
- XX endif
- XX mov ax,0 ;Patch Ourselves into
- XX mov es,ax ;the INT 24 Vector
- XX mov ax,es:[vect_int_24] ;Offset
- XX mov word ptr orig_int_24,ax
- XX lea ax,our_int_24
- XX mov es:[vect_int_24],ax
- XX mov ax,es:[vect_int_24+2] ;Segment
- XX mov word ptr orig_int_24+2,ax
- XX mov ax,cs
- XX mov es:[vect_int_24+2],ax
- XX jmp done
- XX
- XX;
- XX; Close Tape Device
- XX;
- XXCLOSE_DEV: mov di,tape_unit
- XX cmp di,-1 ;Do We have a SCSITAPE: Unit?
- XX jnz close_tape
- XX jmp bad_unit
- XXclose_tape: mov ax,0 ;Restore
- XX mov es,ax ;the INT 24 Vector
- XX mov word ptr orig_int_24,ax
- XX mov es:[vect_int_24],ax ;Offset
- XX mov word ptr orig_int_24+2,ax
- XX mov es:[vect_int_24+2],ax ;Segment
- XX mov cur_unit,di ;New Current Unit
- XX cmp error_flag,TRUE ;Any Tape Errors
- XX jz skip_extras
- XX cmp write_flag,TRUE ;Were We Writing?
- XX jnz not_writing
- XX lea di,cmd_twritefm ;End Tape with FM(s)
- XX mov [di].fm_cmd_cnt_b0,CLOSE_FM_CNT
- XX call docmd
- XX jnc skip_extras
- XX call get_sense
- XX jmp short skip_extras
- XXnot_writing: cmp read_flag,TRUE ;Were We Reading?
- XX jnz skip_extras
- XX cmp load_flag,TRUE ;No Rewind?
- XX jz skip_extras
- XX lea di,cmd_space ;Space Forward
- XX mov [di].space_cmd_code,1 ;By FileMark
- XX mov [di].space_cmd_cnt2,0
- XX mov [di].space_cmd_cnt1,0
- XX mov [di].space_cmd_cnt0,1
- XX call docmd
- XX jnc skip_extras
- XX call get_sense
- XXskip_extras: cmp load_flag,TRUE ;Should we Unload?
- XX jnz close_ok
- XX ife mini_inquire
- XX mov di,cur_unit ;Check Unit Type
- XX mov ax,word ptr [di].unit_inq_buf.inq_manufact
- XX lea di,cmd_rewind
- XX cmp ax,'ET' ;Rewind instead of
- XX jz close_rewind ;Unload TEAC Unit
- XX endif
- XX lea di,cmd_load ;Now Unload Tape
- XX mov [di].load_cmd_type,UNLOAD_TAPE
- XXclose_rewind: call docmd
- XX jnc close_ok
- XX call scsi_sense
- XX jmp general
- XXclose_ok: jmp done
- XX
- XX;
- XX; Get Device Assignment
- XX;
- XXGET_DEV: mov es:[bx].rh_unit,0
- XX jmp done
- XX
- XX;
- XX; Set Device Assignment
- XX;
- XXSET_DEV: jmp done
- XX
- XXbad_unit: mov es,rh_seg ;Point us at the Request Header
- XX mov bx,rh_off
- XX or es:[bx].rh_status,8001h
- XX jmp short done
- XX
- XXunknown: mov es,rh_seg ;Point us at the Request Header
- XX mov bx,rh_off
- XX or es:[bx].rh_status,8003h
- XX jmp short done
- XX
- XXbad_write: mov es,rh_seg ;Point us at the Request Header
- XX mov bx,rh_off
- XX or es:[bx].rh_status,800Ah
- XX jmp short done
- XX
- XXbad_read: mov es,rh_seg ;Point us at the Request Header
- XX mov bx,rh_off
- XX or es:[bx].rh_status,800Bh
- XX jmp short done
- XX
- XXgeneral: mov es,rh_seg ;Point us at the Request Header
- XX mov bx,rh_off
- XX or es:[bx].rh_status,800Ch
- XX jmp short done
- XX
- XXbusy: mov es,rh_seg ;Point us at the Request Header
- XX mov bx,rh_off
- XX or es:[bx].rh_status,0200h
- XX
- XXdone: mov es,rh_seg ;Point us at the Request Header
- XX mov bx,rh_off
- XX or es:[bx].rh_status,0100h
- XX
- XX cli ;Make sure we're left alone
- XX mov ax,cs:stack_seg ;Restore DOS Stack
- XX mov ss,ax
- XX mov ax,cs:stack_ptr
- XX mov sp,ax
- XX
- XX pop bp ;Restore All Registers
- XX pop di
- XX pop si
- XX pop dx
- XX pop cx
- XX pop bx
- XX pop ax
- XX pop es
- XX pop ds
- XX popf
- XX ret
- XX
- XX INCLUDE units.asm
- XX INCLUDE subs.asm
- XX INCLUDE ioctl.asm
- XX INCLUDE dump.asm
- XX if use_kludge
- XX INCLUDE kludge.asm
- XX endif
- XX
- XX;
- XX; End of Program
- XX; Stuff Placed Here Gets Handed Back To DOS For Re-use
- XX;
- XXinitial proc near
- XX lea dx,hello_msg ;Tell them the driver version
- XX call puts
- XX push cs
- XX pop dx
- XX lea bx,seg_msg_value
- XX call hex2asc4
- XX lea dx,seg_msg ;And Were We Loaded
- XX call puts
- XX
- XX call scsi_reset ;Reset the bus
- XX
- XX mov cx,0 ;Scan for devices
- XXscan: mov ax,cx
- XX add al,030h
- XX mov scan_dev,al
- XX mov ax,1 ;Create Select Bit
- XX shl ax,cl
- XX mov di,cur_unit
- XX mov [di].unit_select,al
- XX mov [di].unit_num_drv,0 ;No Drives to start with
- XX mov al,disk_count ;We will start with
- XX mov [di].unit_1st_drv,al ;Drive Number if any
- XX
- XX lea dx,scan_dev ;Print the device number
- XX call puts
- XX call scsi_inquire ;Inquire as to its type
- XX jnc scan_inq_ok
- XX
- XX lea dx,no_dev ;If the error was
- XX cmp al,CNOCONNECT ;'No Such Device'
- XX jz puts_jmp
- XX
- XX lea dx,dumb_disk_msg ;Assume it is a 'SCSI I'
- XX jmp short scan_is_drv ;Old style disk
- XX
- XXscan_inq_ok: mov di,cur_unit
- XX if mini_inquire
- XX lea dx,disk_dev_msg
- XX else
- XX lea dx,[di].unit_inq_buf.inq_manufact
- XX mov [di].unit_inq_term,'$'
- XX endif
- XX mov al,[di].unit_inq_buf.inq_dev_type
- XX or al,al ;Look at device type
- XX jz scan_is_drv
- XX if mini_inquire
- XX lea dx,tape_dev_msg
- XX endif
- XX cmp tape_unit,-1 ;Do We Already Have A Tape?
- XX jnz puts_jmp
- XX call puts ;Make this our SCSITAPE: Unit
- XX mov tape_unit,di
- XX lea dx,tape_msg
- XXputs_jmp: jmp scan_puts
- XX
- XXscan_is_drv: call puts ;Output the Device String
- XX call scsi_capacity ;Inquire as to its size
- XX lea dx,err_size
- XX jc scan_puts ;Do not use unknown drives
- XX lea dx,crlf
- XX call puts
- XX
- XXscan_next_drv: mov di,cur_unit
- XX mov al,disk_count ;Number Of Drives Found
- XX inc al
- XX mov disk_count,al
- XX mov al,[di].unit_num_drv ;We have a valid Drive
- XX inc al
- XX mov [di].unit_num_drv,al
- XX mov al,cur_drive ;Get Current Drive Letter
- XX mov drv_msg_let,al ;Insert it in message
- XX inc al ;Bump Drive Letter
- XX mov cur_drive,al
- XX call make_bpb ;Setup the BPB for this drive
- XX mov di,cur_bpb ;Current Working BPB
- XX if large_drives
- XX mov dx,[di].bpb_ts_msw
- XX mov ax,[di].bpb_ts_lsw
- XX else
- XX mov dx,0
- XX mov ax,[di].bpb_ts
- XX endif
- XX mov bx,2048
- XX div bx
- XX inc ax
- XX lea bx,drv_msg_size
- XX call bin_ascii
- XX mov bx,bpb_hw_mark ;Get the BPB High Water Mark
- XX inc bx ;Bump HW Mark for next time
- XX inc bx
- XX mov ax,[bx] ;Get the BPB
- XX mov cur_bpb,ax ;Make it the current BPB
- XX mov bpb_hw_mark,bx
- XX lea dx,drv_msg
- XX call puts
- XX ife large_drives
- XX mov bx,cur_unit
- XX mov ah,0
- XX mov al,[bx].unit_num_drv ;Insert Drive Offset
- XX dec al ;Into BPB for this Drive
- XX mov [di].bpb_hs_msw,ax
- XX mov al,[bx].unit_cap_buf.cap_sectors_b3
- XX or al,[bx].unit_cap_buf.cap_sectors_b2
- XX or al,[bx].unit_cap_buf.cap_sectors_b1
- XX or al,[bx].unit_cap_buf.cap_sectors_b0
- XX jnz scan_next_drv ;Room left for another Drive
- XX endif
- XX jmp short scan_next
- XX
- XXscan_puts: call puts
- XX lea dx,crlf
- XX call puts
- XX
- XXscan_next: inc cx
- XX cmp cx,MAXUNIT ;End of devices?
- XX jg scan_exit
- XX mov bx,cx ;Bump to next unit
- XX shl bx,1
- XX mov ax,word ptr unit_array[bx]
- XX mov cur_unit,ax
- XX jmp scan
- XX
- XXscan_exit: lea dx,crlf
- XX call puts
- XX ret
- XXinitial endp
- XX
- XX;
- XX; Data Area Used Only During Initialization
- XX;
- XXhello_msg db 0dh,0ah,'SCSI Device Driver Version 2.0, '
- XX if oldcode
- XX db '8086 Flavor',0Dh,0Ah,'$'
- XX else
- XX db '80286 Flavor',0Dh,0Ah,'$'
- XX endif
- XXseg_msg db 'Driver Loaded At Segment '
- XXseg_msg_value db '0000',0dh,0ah,'$'
- XXscan_dev db 'X - ','$'
- XXno_dev db '(No Installed Device)$'
- XXerr_size db '(Unknown Size)$'
- XXdrv_msg db ' - Drive '
- XXdrv_msg_let db 'X: '
- XXdrv_msg_size db 'XXXXXX Meg',0dh,0ah,'$'
- XXtape_msg db 0dh,0ah,' - Is The SCSITAPE: Device$'
- XXdumb_disk_msg db 'UNKNOWN DUMB DISK $'
- XXcrlf db 0dh,0ah,'$'
- XX if mini_inquire
- XXdisk_dev_msg db 'Disk Device $'
- XXtape_dev_msg db 'Tape Device $'
- XX endif
- XX
- XX
- XXdev_interrupt endp
- XX_TEXT ends
- XX end
- SHAR_EOF
- if test 14291 -ne "`wc -c < 'scsi.asm'`"
- then
- echo shar: error transmitting "'scsi.asm'" '(should have been 14291 characters)'
- fi
- fi # end of overwriting check
- echo shar: extracting "'subs.asm'" '(22277 characters)'
- if test -f 'subs.asm'
- then
- echo shar: will not over-write existing file "'subs.asm'"
- else
- sed 's/^XX//' > 'subs.asm' << \SHAR_EOF
- XX;
- XX; Data storage for local subroutines
- XX;
- XXcmd_ready db SCSI_TESTREADY,0,0,0,0,0
- XXcmd_rewind db SCSI_REWIND,0,0,0,0,0
- XXcmd_sense db SCSI_REQSENSE,0,0,0,size sense,0
- XXcmd_e_sense db SCSI_REQSENSE,0,0,0,size e_sense,0
- XXcmd_format db SCSI_FORMATUNIT,FORMAT_NORMAL,0,0,0,0
- XXcmd_remap db SCSI_REASSIGN,0,0,0,0,0
- XXcmd_space db SCSI_SPACE,1,0,0,0,0
- XX if extended_io
- XXcmd_read db SCSI_READBLK,0,0,0,0,0,0,0,1,0
- XXcmd_write db SCSI_WRITEBLK,0,0,0,0,0,0,0,1,0
- XX else
- XXcmd_read db SCSI_READBLK,0,0,0,1,0
- XXcmd_write db SCSI_WRITEBLK,0,0,0,1,0
- XX endif
- XXcmd_tread db SCSI_READBLK,1,0,0,0,0
- XXcmd_twrite db SCSI_WRITEBLK,1,0,0,0,0
- XXcmd_twritefm db SCSI_WRITEFM,0,0,0,CLOSE_FM_CNT,0
- XXcmd_inquire db SCSI_INQUIRY,0,0,0,size inq,0
- XXcmd_erase db SCSI_ERASE,1,0,0,0,0
- XXcmd_load db SCSI_LOAD,0,0,0,0,0
- XXcmd_capacity db SCSI_READSIZE,0,0,0,0,0,0,0,0,0
- XXcmd_verify db SCSI_VERIFYBLK,0,0,0,0,0,0,0,SECT_TRACK,0
- XX
- XX if large_drives
- XX even
- XXlsect_lsw dw ?
- XXlsect_msw dw ?
- XX endif
- XX
- XX even
- XXdocmd_cmd dw ?
- XXdocmd_buf dw ?
- XXdocmd_buf_seg dw ?
- XXdocmd_len dw ?
- XXdocmd_ustatus db ?
- XXdocmd_estatus db ?
- XXdocmd_message db ?
- XX
- XXsense_ustatus db ?
- XXsense_estatus db ?
- XXsense_message db ?
- XX
- XXretry_cnt db ?
- XX
- XX if dump_sense
- XXsense_msg1 db 0dh,07h,'Unit '
- XXsense_unit db 'xxh, Err '
- XXsense_err db 'xxh, Stat '
- XXsense_ustat db 'xxh, Msg '
- XXsense_msg db 'xxh, Retry '
- XXsense_retry db 'xxh$'
- XXsense_msg2 db ', Sense '
- XXsense_code db 'xxh, Addr '
- XXsense_addr3 db 'xx'
- XXsense_addr2 db 'xx'
- XXsense_addr1 db 'xx'
- XXsense_addr0 db 'xxh$'
- XX ife monitor
- XXsense_msg3 db 0dh,0ah,'$'
- XX endif
- XX endif
- XX
- XX;
- XX; Reset the SCSI Bus
- XX;
- XXscsi_reset proc near
- XX pusha
- XX
- XX mov ax,SCSI_CARD_SEG ;Point at the command port
- XX mov es,ax
- XX mov si,SCSI_CMD_PORT
- XX
- XX mov byte ptr es:[si],CMDBASE or CMDRST
- XX call wait100us
- XX mov byte ptr es:[si],CMDBASE
- XX call wait100us
- XX
- XX popa
- XX ret
- XXscsi_reset endp
- XX
- XX;
- XX; Request Sense data from a unit and display the result
- XX; Called after every SCSI command with the exit code in 'al'
- XX;
- XXscsi_sense proc near
- XX pushf
- XX pusha
- XX push es
- XX
- XX if dump_sense
- XX;
- XX; Print out the first part even if we can't retrieve any sense status
- XX;
- XX mov al,docmd_estatus ;Save for printing
- XX mov sense_estatus,al
- XX mov al,docmd_ustatus
- XX mov sense_ustatus,al
- XX mov al,docmd_message
- XX mov sense_message,al
- XX mov di,cur_unit
- XX mov dl,[di].unit_select
- XX lea bx,sense_unit ;Unit
- XX call hex2asc2
- XX mov dl,sense_estatus ;Error (from docmd)
- XX lea bx,sense_err
- XX call hex2asc2
- XX mov dl,sense_ustatus ;Status (from unit)
- XX lea bx,sense_ustat
- XX call hex2asc2
- XX mov dl,sense_message ;Msg (from unit)
- XX lea bx,sense_msg
- XX call hex2asc2
- XX mov dl,retry_cnt ;Retry
- XX lea bx,sense_retry
- XX call hex2asc2
- XX lea dx,sense_msg1
- XX call puts
- XX endif
- XX
- XX;
- XX; Try to retrieve sense status
- XX;
- XX mov di,cur_unit ;Unit
- XX lea bx,[di].unit_sense ;Buffer Offset
- XX mov cx,size sense ;Buffer Size
- XX lea dx,cmd_sense ;Command
- XX cmp [di].unit_sense.sense_sense,SENSE_CCS
- XX jnz no_e_sense
- XX lea bx,[di].unit_e_sense ;Buffer Offset
- XX mov cx,size e_sense ;Buffer Size
- XX lea dx,cmd_e_sense ;Command
- XXno_e_sense: push ds ;Buffer Segment
- XX pop es
- XX mov di,dx
- XX call docmd
- XX
- XX if dump_sense
- XX;
- XX; If we got something, print it
- XX;
- XX jnc sense_dump
- XX jmp sense_exit
- XX
- XXsense_dump: mov di,cur_unit
- XX cmp [di].unit_sense.sense_sense,SENSE_CCS
- XX jz dump_e_sense
- XX
- XX mov dl,[di].unit_sense.sense_sense
- XX lea bx,sense_code ;Sense
- XX call hex2asc2
- XX mov dl,0
- XX lea bx,sense_addr3
- XX call hex2asc2
- XX mov dl,[di].unit_sense.sense_lba_b2
- XX lea bx,sense_addr2
- XX call hex2asc2
- XX mov dl,[di].unit_sense.sense_lba_b1
- XX lea bx,sense_addr1
- XX call hex2asc2
- XX mov dl,[di].unit_sense.sense_lba_b0
- XX lea bx,sense_addr0
- XX call hex2asc2
- XX jmp short sense_print
- XX
- XXdump_e_sense: mov dl,[di].unit_e_sense.e_sense_sense
- XX lea bx,sense_code ;Sense
- XX call hex2asc2
- XX mov dl,[di].unit_e_sense.e_sense_lba_b3
- XX lea bx,sense_addr3 ;Address
- XX call hex2asc2
- XX mov dl,[di].unit_e_sense.e_sense_lba_b2
- XX lea bx,sense_addr2
- XX call hex2asc2
- XX mov dl,[di].unit_e_sense.e_sense_lba_b1
- XX lea bx,sense_addr1
- XX call hex2asc2
- XX mov dl,[di].unit_e_sense.e_sense_lba_b0
- XX lea bx,sense_addr0
- XX call hex2asc2
- XX
- XXsense_print: lea dx,sense_msg2
- XX call puts
- XX endif
- XX
- XXsense_exit: if dump_sense
- XX if monitor
- XX mov cx,20000
- XXsense_wait: call wait100us
- XX loop sense_wait
- XX else
- XX lea dx,sense_msg3 ;Terminate the Message
- XX call puts
- XX endif
- XX endif
- XX
- XX pop es
- XX popa
- XX popf
- XX ret
- XXscsi_sense endp
- XX
- XX;
- XX; Get the Extended Sense Status from the current Unit
- XX;
- XXget_sense proc near
- XX mov di,cur_unit ;Unit
- XX lea bx,[di].unit_e_sense ;Buffer Offset
- XX push ds ;Buffer Segment
- XX pop es
- XX mov cx,size e_sense ;Buffer Size
- XX lea di,cmd_e_sense ;Command
- XX call docmd ;Always ask first
- XX ret
- XXget_sense endp
- XX
- XX;
- XX; Inquire about the type of a unit
- XX;
- XX; This MUST be the first call to a unit after the reset is done!
- XX;
- XX; al = return code, 'C' error indicates an error
- XX;
- XXscsi_inquire proc near
- XX push cx
- XX
- XX;
- XX; First thing we should do is wait for the unit to be ready
- XX; as it takes some drives a while to spin up.
- XX;
- XX mov retry_cnt,READY_RETRY
- XXready_loop1: lea di,cmd_ready ;Command
- XX call docmd
- XX jnc unit_is_ready
- XX cmp al,CNOCONNECT ;No such unit?
- XX jz ready_error
- XX push cx
- XX mov cx,10000 ;Wait 1 Second
- XXready_loop2: call wait100us
- XX loop ready_loop2
- XX pop cx
- XX dec retry_cnt ;RETRY Times
- XX jns ready_loop1
- XX jmp short unit_is_ready ;Still Try the Inquire
- XXready_error: stc
- XX jmp short inquire_exit
- XX
- XX;
- XX; Then requests its sense status.
- XX; This gives us a chance to find out if the
- XX; device supports the Command Command Set (CCS)
- XX;
- XXunit_is_ready: call get_sense
- XX jc inquire_exit
- XX
- XX;
- XX; Ok, Now find out what kind of device it is
- XX;
- XX mov di,cur_unit ;Unit
- XX lea bx,[di].unit_inq_buf ;Buffer Offset
- XX push ds ;Buffer Segment
- XX pop es
- XX mov cx,size inq ;Buffer Size
- XX lea di,cmd_inquire ;Command
- XX call docmd
- XX
- XXinquire_exit: pop cx
- XX ret
- XXscsi_inquire endp
- XX
- XX;
- XX; Determine the size of a disk
- XX;
- XX; al = return code, 'C' error indicates an error
- XX;
- XXscsi_capacity proc near
- XX push cx
- XX mov retry_cnt,MAX_RETRY
- XX
- XXcapacity_retry: mov di,cur_unit ;Unit
- XX lea bx,[di].unit_cap_buf ;Buffer Offset
- XX push ds ;Buffer Segment
- XX pop es
- XX mov cx,size cap ;Buffer Size
- XX lea di,cmd_capacity ;Command
- XX call docmd
- XX jnc capacity_exit
- XX call scsi_sense
- XX dec retry_cnt
- XX jns capacity_retry
- XX stc
- XX
- XXcapacity_exit: pop cx
- XX ret
- XXscsi_capacity endp
- XX
- XX;
- XX; Verify (cx) Sectors starting with (dx:ax)
- XX;
- XX; al = return code, 'C' indicates an error
- XX;
- XX
- XXscsi_verify proc near
- XX mov retry_cnt,0 ;Don't do retrys
- XX lea di,cmd_verify ;Command
- XX mov [di].ver_cmd_lba_b3,dh ;Insert Sector
- XX mov [di].ver_cmd_lba_b2,dl ; into Command
- XX mov [di].ver_cmd_lba_b1,ah ;Insert Sector
- XX mov [di].ver_cmd_lba_b0,al ; into Command
- XX mov [di].ver_cmd_len_b1,ch ;Insert Length
- XX mov [di].ver_cmd_len_b0,cl ; into Command
- XX call docmd
- XX jnc verify_exit
- XX call scsi_sense
- XX
- XXverify_exit: ret
- XXscsi_verify endp
- XX
- XX;
- XX; Read Some Blocks from the disk given
- XX; the request header in es:bx
- XX;
- XX; al = return code, 'C' indicates an error
- XX;
- XXdisk_read proc near
- XX mov retry_cnt,MAX_RETRY
- XX
- XX mov di,bx
- XX mov cx,es:[di].rh4_count ;Sector Count
- XX if large_drives
- XX mov dx,es:[di].rh4_lsect_lsw ;Starting Sector
- XX mov lsect_lsw,dx
- XX mov dx,es:[di].rh4_lsect_msw
- XX mov lsect_msw,dx
- XX else
- XX mov dx,es:[di].rh4_sector ;Starting Sector
- XX endif
- XX mov bx,es:[di].rh4_buf_ofs ;Buffer Offset
- XX mov ax,es:[di].rh4_buf_seg ;Buffer Segment
- XX mov es,ax
- XX
- XX mov si,cur_bpb
- XX lea di,cmd_read ;Command
- XX ife large_drives
- XX mov ax,[si].bpb_hs_msw ;Drive Sector Offset
- XX if extended_io
- XX mov [di].io_cmd_lba_b3,ah ;Insert Sector
- XX endif
- XX mov [di].io_cmd_lba_b2,al ;Into the Command
- XX endif
- XX
- XX if multi_sector
- XX mov ax,cx ;Get Sector Count
- XX and ax,CHUNK_MAX-1 ;Mask Off the I/O Chunk
- XX jnz disk_r_cok1 ;Check for Boundary
- XX mov ax,CHUNK_MAX
- XX if oldcode
- XXdisk_r_cok1: shl ax,1 ;Convert to Buffer Size
- XX shl ax,1
- XX shl ax,1
- XX shl ax,1
- XX shl ax,1
- XX shl ax,1
- XX shl ax,1
- XX shl ax,1
- XX shl ax,1
- XX else
- XXdisk_r_cok1: shl ax,9 ;Convert to Buffer Size
- XX endif
- XX add ax,bx ;Check for Wrap
- XX else
- XX mov ax,bx ;Check for Wrap
- XX add ax,P_SECT ;The First Time
- XX endif
- XXdisk_r_loop: jnc disk_r_nowrap
- XX mov ax,bx ;Normalize the
- XX if oldcode
- XX shr ax,1 ;Segment and
- XX shr ax,1
- XX shr ax,1
- XX shr ax,1
- XX else
- XX shr ax,4 ;Segment and
- XX endif
- XX mov si,es ;Offset so that
- XX add si,ax ;It dosn't Wrap
- XX mov es,si
- XX and bx,000Fh
- XXdisk_r_nowrap: push cx
- XX if large_drives
- XX mov dx,lsect_msw
- XX if extended_io
- XX mov [di].io_cmd_lba_b3,dh
- XX mov [di].io_cmd_lba_b2,dl
- XX else
- XX and dl,01Fh
- XX mov [di].io_cmd_lba_b2,dl
- XX endif
- XX mov dx,lsect_lsw
- XX endif
- XX mov [di].io_cmd_lba_b1,dh ;Insert Sector
- XX mov [di].io_cmd_lba_b0,dl ;Into the Command
- XX if multi_sector
- XX and cx,CHUNK_MAX-1 ;Mask Off the I/O Chunk
- XX jnz disk_r_cok2 ;Check for Boundary
- XX mov cx,CHUNK_MAX
- XXdisk_r_cok2:
- XX if extended_io
- XX mov [di].io_cmd_cnt_b1,ch ;Insert Sector Count
- XX endif
- XX mov [di].io_cmd_cnt_b0,cl ;Into the Command
- XX if oldcode
- XX shl cx,1 ;Convert to Buffer Size
- XX shl cx,1
- XX shl cx,1
- XX shl cx,1
- XX shl cx,1
- XX shl cx,1
- XX shl cx,1
- XX shl cx,1
- XX shl cx,1
- XX else
- XX shl cx,9 ;Convert to Buffer Size
- XX endif
- XX else
- XX mov cx,P_SECT ;Buffer Size
- XX endif
- XXdisk_r_retry: call docmd
- XX jnc disk_r_cok3
- XX call scsi_sense
- XX dec retry_cnt
- XX jns disk_r_retry ;Already Setup
- XX pop cx
- XX stc
- XX jmp short disk_r_exit
- XX if multi_sector
- XXdisk_r_cok3: pop cx
- XX mov ax,cx ;Get Sector Count
- XX and ax,CHUNK_MAX-1 ;Mask Off the I/O Chunk
- XX jnz disk_r_cok4 ;Check for Boundary
- XX mov ax,CHUNK_MAX
- XXdisk_r_cok4: sub cx,ax ;Dec Sector Count
- XX jz disk_r_exit
- XX if large_drives
- XX add lsect_lsw,ax ;Bump to next Sector
- XX adc lsect_msw,0
- XX else
- XX add dx,ax ;Bump to next Sector
- XX endif
- XX if oldcode
- XX shl ax,1 ;Convert to Buffer Size
- XX shl ax,1
- XX shl ax,1
- XX shl ax,1
- XX shl ax,1
- XX shl ax,1
- XX shl ax,1
- XX shl ax,1
- XX shl ax,1
- XX else
- XX shl ax,9 ;Convert to Buffer Size
- XX endif
- XX add bx,ax
- XX jmp disk_r_loop
- XX else
- XXdisk_r_cok3: pop cx
- XX if large_drives
- XX add lsect_lsw,1 ;Bump to next Sector
- XX adc lsect_msw,0
- XX else
- XX inc dx ;Bump to next Sector
- XX endif
- XX add bx,P_SECT
- XX loop disk_r_loop
- XX clc
- XX endif
- XX
- XXdisk_r_exit: mov es,rh_seg
- XX mov bx,rh_off
- XX pushf
- XX mov ax,es:[bx].rh4_count ;Update the Count
- XX sub ax,cx
- XX mov es:[bx].rh4_count,ax
- XX popf
- XX ret
- XXdisk_read endp
- XX
- XX;
- XX; Write Some Blocks to the disk given
- XX; the request header in es:bx
- XX;
- XX; al = return code, 'C' indicates an error
- XX;
- XXdisk_write proc near
- XX mov retry_cnt,MAX_RETRY
- XX
- XX mov di,bx
- XX mov cx,es:[di].rh8_count ;Sector Count
- XX if large_drives
- XX mov dx,es:[di].rh8_lsect_lsw ;Starting Sector
- XX mov lsect_lsw,dx
- XX mov dx,es:[di].rh8_lsect_msw
- XX mov lsect_msw,dx
- XX else
- XX mov dx,es:[di].rh8_sector ;Starting Sector
- XX endif
- XX mov bx,es:[di].rh8_buf_ofs ;Buffer Offset
- XX mov ax,es:[di].rh8_buf_seg ;Buffer Segment
- XX mov es,ax
- XX
- XX mov si,cur_bpb
- XX lea di,cmd_write ;Command
- XX ife large_drives
- XX mov ax,[si].bpb_hs_msw ;Drive Sector Offset
- XX if extended_io
- XX mov [di].io_cmd_lba_b3,ah ;Insert Sector
- XX endif
- XX mov [di].io_cmd_lba_b2,al ;Into the Command
- XX endif
- XX
- XX if multi_sector
- XX mov ax,cx ;Get Sector Count
- XX and ax,CHUNK_MAX-1 ;Mask Off the I/O Chunk
- XX jnz disk_w_cok1 ;Check for Boundary
- XX mov ax,CHUNK_MAX
- XX if oldcode
- XXdisk_w_cok1: shl ax,1 ;Convert to Buffer Size
- XX shl ax,1
- XX shl ax,1
- XX shl ax,1
- XX shl ax,1
- XX shl ax,1
- XX shl ax,1
- XX shl ax,1
- XX shl ax,1
- XX else
- XXdisk_w_cok1: shl ax,9 ;Convert to Buffer Size
- XX endif
- XX add ax,bx ;Check for Wrap
- XX else
- XX mov ax,bx ;Check for Wrap
- XX add ax,P_SECT ;The First Time
- XX endif
- XXdisk_w_loop: jnc disk_w_nowrap
- XX mov ax,bx ;Normalize the
- XX if oldcode
- XX shr ax,1 ;Segment and
- XX shr ax,1
- XX shr ax,1
- XX shr ax,1
- XX else
- XX shr ax,4 ;Segment and
- XX endif
- XX mov si,es ;Offset so that
- XX add si,ax ;It dosn't Wrap
- XX mov es,si
- XX and bx,000Fh
- XXdisk_w_nowrap: push cx
- XX if large_drives
- XX mov dx,lsect_msw
- XX if extended_io
- XX mov [di].io_cmd_lba_b3,dh
- XX mov [di].io_cmd_lba_b2,dl
- XX else
- XX and dl,01Fh
- XX mov [di].io_cmd_lba_b2,dl
- XX endif
- XX mov dx,lsect_lsw
- XX endif
- XX mov [di].io_cmd_lba_b1,dh ;Insert Sector
- XX mov [di].io_cmd_lba_b0,dl ;Into the Command
- XX if multi_sector
- XX and cx,CHUNK_MAX-1 ;Mask Off the I/O Chunk
- XX jnz disk_w_cok2 ;Check for Boundary
- XX mov cx,CHUNK_MAX
- XXdisk_w_cok2:
- XX if extended_io
- XX mov [di].io_cmd_cnt_b1,ch ;Insert Sector Count
- XX endif
- XX mov [di].io_cmd_cnt_b0,cl ;Into the Command
- XX if oldcode
- XX shl cx,1 ;Convert to Buffer Size
- XX shl cx,1
- XX shl cx,1
- XX shl cx,1
- XX shl cx,1
- XX shl cx,1
- XX shl cx,1
- XX shl cx,1
- XX shl cx,1
- XX else
- XX shl cx,9 ;Convert to Buffer Size
- XX endif
- XX else
- XX mov cx,P_SECT ;Buffer Size
- XX endif
- XXdisk_w_retry: call docmd
- XX jnc disk_w_cok3
- XX call scsi_sense
- XX dec retry_cnt
- XX jns disk_w_retry ;Already Setup
- XX pop cx
- XX stc
- XX jmp short disk_w_exit
- XX if multi_sector
- XXdisk_w_cok3: pop cx
- XX mov ax,cx ;Get Sector Count
- XX and ax,CHUNK_MAX-1 ;Mask Off the I/O Chunk
- XX jnz disk_w_cok4 ;Check for Boundary
- XX mov ax,CHUNK_MAX
- XXdisk_w_cok4: sub cx,ax ;Dec Sector Count
- XX jz disk_w_exit
- XX if large_drives
- XX add lsect_lsw,ax ;Bump to next Sector
- XX adc lsect_msw,0
- XX else
- XX add dx,ax ;Bump to next Sector
- XX endif
- XX if oldcode
- XX shl ax,1 ;Convert to Buffer Size
- XX shl ax,1
- XX shl ax,1
- XX shl ax,1
- XX shl ax,1
- XX shl ax,1
- XX shl ax,1
- XX shl ax,1
- XX shl ax,1
- XX else
- XX shl ax,9 ;Convert to Buffer Size
- XX endif
- XX add bx,ax
- XX jmp disk_w_loop
- XX else
- XXdisk_w_cok3: pop cx
- XX if large_drives
- XX add lsect_lsw,1 ;Bump to next Sector
- XX adc lsect_msw,0
- XX else
- XX inc dx ;Bump to next Sector
- XX endif
- XX add bx,P_SECT
- XX loop disk_w_loop
- XX clc
- XX endif
- XX
- XXdisk_w_exit: mov es,rh_seg
- XX mov bx,rh_off
- XX pushf
- XX mov ax,es:[bx].rh8_count ;Update the Count
- XX sub ax,cx
- XX mov es:[bx].rh8_count,ax
- XX popf
- XX ret
- XXdisk_write endp
- XX
- XX;
- XX; Read Some Blocks from the Tape
- XX;
- XXtape_read proc near
- XX mov read_flag,TRUE ;Data Read from Tape
- XX mov di,bx
- XX mov cx,es:[di].rh4_count ;Byte Count
- XX mov ax,cx ;Test for invalid
- XX and ax,P_SECT-1 ;Byte Count
- XX jz tape_r_valid
- XX mov error_flag,TRUE
- XX mov es:[di].rh4_count,0 ;Nothing Read
- XX stc ;Oops
- XX ret
- XXtape_r_valid: mov bx,es:[di].rh4_buf_ofs ;Buffer Offset
- XX mov ax,es:[di].rh4_buf_seg ;Buffer Segment
- XX mov es,ax
- XX mov ax,bx ;Normalize the
- XX if oldcode
- XX shr ax,1 ;Segment and
- XX shr ax,1
- XX shr ax,1
- XX shr ax,1
- XX else
- XX shr ax,4 ;Segment and
- XX endif
- XX mov si,es ;Offset so that
- XX add si,ax ;It dosn't Wrap
- XX mov es,si
- XX and bx,000Fh
- XX lea di,cmd_tread
- XX mov ax,cx ;Convert Bytes
- XX if oldcode
- XX shr ax,1 ;to Blocks
- XX shr ax,1
- XX shr ax,1
- XX shr ax,1
- XX shr ax,1
- XX shr ax,1
- XX shr ax,1
- XX shr ax,1
- XX shr ax,1
- XX else
- XX shr ax,9 ;to Blocks
- XX endif
- XX mov [di].tio_cmd_cnt_b1,ah ;Insert into Command
- XX mov [di].tio_cmd_cnt_b0,al
- XX call docmd
- XX jnc tape_r_ok
- XX;
- XX; Get the Extended Sense Status to check for reading FileMark
- XX;
- XX call get_sense ;Get Extended Sense
- XX jc tape_r_kaboom
- XX mov di,cur_unit ;Unit
- XX cmp [di].unit_e_sense.e_sense_sense,80h
- XX jnz tape_r_eom
- XXtape_r_kaboom: mov error_flag,TRUE ;Real Error Occured
- XX stc
- XX ret
- XXtape_r_eom: mov es,rh_seg
- XX mov bx,rh_off
- XX mov es:[bx].rh4_count,0 ;Nothing Read
- XX clc
- XXtape_r_ok: ret
- XXtape_read endp
- XX
- XX;
- XX; Write Some Blocks to the Tape
- XX;
- XXtape_write proc near
- XX mov write_flag,TRUE ;Data Written to Tape
- XX mov di,bx
- XX mov cx,es:[di].rh8_count ;Byte Count
- XX mov ax,cx ;Test for invalid
- XX and ax,P_SECT-1 ;Byte Count
- XX jz tape_w_valid
- XX mov es:[di].rh8_count,0 ;Nothing Written
- XX mov error_flag,TRUE ;ERROR!
- XX stc ;Oops
- XX ret
- XXtape_w_valid: mov cx,es:[di].rh8_count ;Byte Count
- XX mov bx,es:[di].rh8_buf_ofs ;Buffer Offset
- XX mov ax,es:[di].rh8_buf_seg ;Buffer Segment
- XX mov es,ax
- XX mov ax,bx ;Normalize the
- XX if oldcode
- XX shr ax,1 ;Segment and
- XX shr ax,1
- XX shr ax,1
- XX shr ax,1
- XX else
- XX shr ax,4 ;Segment and
- XX endif
- XX mov si,es ;Offset so that
- XX add si,ax ;It dosn't Wrap
- XX mov es,si
- XX and bx,000Fh
- XX lea di,cmd_twrite
- XX mov ax,cx ;Convert Bytes
- XX if oldcode
- XX shr ax,1 ;to Blocks
- XX shr ax,1
- XX shr ax,1
- XX shr ax,1
- XX shr ax,1
- XX shr ax,1
- XX shr ax,1
- XX shr ax,1
- XX shr ax,1
- XX else
- XX shr ax,9 ;to Blocks
- XX endif
- XX mov [di].tio_cmd_cnt_b1,ah ;Insert into Command
- XX mov [di].tio_cmd_cnt_b0,al
- XX call docmd
- XX jnc tape_w_ok
- XX;
- XX; Get the Sense Status and see if we hit EOM.
- XX; This is to allow the FileMark to still be written
- XX; during the close processing.
- XX;
- XX call get_sense ;Get Extended Sense
- XX jc tape_w_kaboom
- XX mov di,cur_unit ;Unit
- XX cmp [di].unit_e_sense.e_sense_sense,40h
- XX jz tape_w_eom
- XXtape_w_kaboom: mov error_flag,TRUE ;Real Error Occured
- XX mov es,rh_seg
- XX mov bx,rh_off
- XX mov es:[bx].rh8_count,0 ;Nothing Written
- XXtape_w_eom: stc
- XXtape_w_ok: ret
- XXtape_write endp
- XX
- XX;
- XX; Do a command
- XX;
- XX; bx = buffer offset
- XX; es = buffer segment
- XX; cx = buffer len
- XX; di => command string
- XX;
- XX; al = return code, 'C' indicates an error
- XX;
- XXdocmd proc near
- XX pusha
- XX push es
- XX
- XX mov docmd_buf,bx ;Save our arguments
- XX mov docmd_buf_seg,es
- XX mov docmd_len,cx
- XX mov docmd_cmd,di
- XX mov docmd_ustatus,0FFh
- XX
- XX if monitor
- XX mov ax,'F' ;Arbitrate for Bus
- XX call show_phase
- XX endif
- XX
- XX mov ax,SCSI_CARD_SEG ;Point at the Card
- XX mov es,ax
- XX mov si,SCSI_CMD_PORT ;Command Port
- XX mov di,SCSI_DATA_PORT ;Data Port
- XX mov bx,cur_unit
- XX mov al,[bx].unit_select ;Get our Select Bit
- XX
- XX if reserve_addr
- XX;
- XX; Get us control of the BUS by starting Arbitration
- XX; Wait a maximum of 250ms for Control of the Bus
- XX;
- XX or al,080h ;Add our Address
- XX mov byte ptr es:[si],CMDBASE
- XX nop
- XX mov byte ptr es:[di],080h ;Our Address
- XX nop
- XX mov byte ptr es:[si],CMDBASE or CMDSTARB
- XX mov cx,2500
- XXarb_loop: test byte ptr es:[si],STARBCOMPL
- XX jnz try_sel
- XX call wait100us
- XX loop arb_loop
- XX else
- XX;
- XX; Wait 250ms for the Bus to become free
- XX;
- XX mov cx,2500
- XXidle_loop: test byte ptr es:[si],STBSY ;Busy?
- XX jz try_sel
- XX call wait100us
- XX loop idle_loop
- XX endif
- XX
- XX call scsi_reset
- XX mov al,CBUSBUSY ;Bus still BUSY?
- XX jmp docmd_exit
- XX
- XXtry_sel: mov byte ptr es:[di],al ;Select Bit
- XX nop
- XX mov byte ptr es:[si],CMDBASE or CMDENABLE or CMDSEL
- XX
- XX if monitor
- XX mov ax,'S' ;Select Target
- XX call show_phase
- XX endif
- XX
- XX;
- XX; Wait 250 ms for the Target to be SELected
- XX;
- XX mov cx,2500
- XXsel_loop: test byte ptr es:[si],STBSY ;Wait for BSY
- XX jnz cmd_xfer
- XX call wait100us
- XX loop sel_loop
- XX
- XX if monitor
- XX mov ax,'A' ;Abort Selection
- XX call show_phase
- XX endif
- XX
- XX mov byte ptr es:[si],CMDBASE or CMDSEL
- XX call wait100us ;Spec says wait 200us
- XX call wait100us ;to abort selection phase
- XX test byte ptr es:[si],STBSY ;Look one final time
- XX jnz cmd_xfer ;Device did answer
- XX mov al,CNOCONNECT ;Nothing Answered
- XX jmp docmd_exit
- XX
- XX;
- XX; Start the Command, (al) contains last known status
- XX;
- XXcmd_xfer: mov byte ptr es:[si],CMDBASE or CMDENABLE
- XX nop
- XXxfer_loop: mov al,es:[si] ;Get Status Byte
- XX test al,STBSY ;Look for BSY bit
- XX jnz still_busy
- XX jmp xfer_offline
- XX if scsi_parity
- XXstill_busy: test al,STPARERR ;Parity Error?
- XX jz still_good
- XX jmp xfer_parerr
- XXstill_good: test al,STREQ ;Request?
- XX jz xfer_loop
- XX else
- XXstill_busy: test al,STREQ ;Request?
- XX jz xfer_loop
- XX endif
- XX
- XX;
- XX; Figure out what type of request it is
- XX;
- XX and al,REQ_MASK
- XX cmp al,REQ_CMDOUT ;Is it Command Out?
- XX jnz try_dataout
- XX
- XX if monitor
- XX mov ax,'C' ;Command
- XX call show_phase
- XX endif
- XX
- XX mov si,docmd_cmd ;Get Command Pointer
- XX movsb ;Send Byte to Card
- XX mov docmd_cmd,si
- XX mov si,SCSI_CMD_PORT ;Restore Command Port
- XX mov di,SCSI_DATA_PORT ;Restore Data Port
- XX jmp xfer_loop
- XX
- XXtry_dataout: cmp al,REQ_DATAOUT ;Is it Data Out?
- XX jnz try_datain
- XX
- XX if monitor
- XX mov ax,'W' ;Write
- XX call show_phase
- XX endif
- XX
- XX mov bx,si
- XX mov cx,docmd_len ;Get the Data Count
- XX mov si,docmd_buf ;Source Offset
- XX mov ds,docmd_buf_seg ;Source Segment
- XX cld
- XX
- XXdataout_loop: test byte ptr es:[bx],STBSY ;Must be BUSY
- XX jz dataout_exit
- XX test byte ptr es:[bx],STREQ ;Wait for REQ
- XX jz dataout_loop
- XX movsb ;Transfer a Byte
- XX dec di ;Keep in Valid
- XX loop dataout_loop ;Done Yet?
- XX
- XXdataout_exit: mov si,bx ;Restore the Environment
- XX mov ax,cs
- XX mov ds,ax
- XX jmp xfer_loop
- XX
- XXtry_datain: cmp al,REQ_DATAIN ;Is it Data In?
- XX jnz try_statin
- XX
- XX if monitor
- XX mov ax,'R' ;Read
- XX call show_phase
- XX endif
- XX
- XX mov bx,si
- XX mov si,di ;Source Offset
- XX mov ax,es
- XX mov cx,docmd_len ;Length
- XX mov di,docmd_buf ;Dest Offset
- XX mov es,docmd_buf_seg ;Dest Segment
- XX mov ds,ax ;Source Segment
- XX cld
- XX
- XXdatain_loop: test byte ptr [bx],STBSY ;Must be BUSY
- XX jz datain_exit
- XX test byte ptr [bx],STREQ ;Wait for REQ
- XX jz datain_loop
- XX movsb ;Transfer a Byte
- XX dec si ;Keep in Valid
- XX loop datain_loop ;Done Yet?
- XX
- XXdatain_exit: mov ax,ds ;Restore the Environment
- XX mov es,ax
- XX mov ax,cs
- XX mov ds,ax
- XX mov di,si
- XX mov si,bx
- XX jmp xfer_loop
- XX
- XXtry_statin: cmp al,REQ_STATIN ;Is it Status In?
- XX jnz try_msgout
- XX
- XX if monitor
- XX mov ax,'s' ;Status
- XX call show_phase
- XX endif
- XX
- XX mov al,es:[di] ;Get the Status Byte
- XX mov docmd_ustatus,al
- XX jmp xfer_loop
- XX
- XXtry_msgout: cmp al,REQ_MSGOUT ;Is it Message Out?
- XX jnz try_msgin
- XX
- XX if monitor
- XX mov ax,'M' ;Message Out
- XX call show_phase
- XX endif
- XX
- XX mov byte ptr es:[di],MSG_REJECT
- XX jmp xfer_loop
- XX
- XXtry_msgin: cmp al,REQ_MSGIN ;Is it Message In?
- XX jnz kaboom
- XX
- XX if monitor
- XX mov ax,'m' ;Message In
- XX call show_phase
- XX endif
- XX
- XX mov al,es:[di] ;Get the MSG Byte
- XX mov docmd_message,al ;And Save it
- XX cmp al,MSG_COMPLETE ;Are We All Done?
- XX jnz xfer_error
- XX cmp docmd_ustatus,0 ;Did we have an error?
- XX mov al,COK ;Preload OK code
- XX jz docmd_exit
- XX jmp xfer_error ;Oops
- XX
- XXkaboom: call scsi_reset ;Reset the BUS
- XX
- XX if monitor
- XX mov ax,'?' ;Message In
- XX call show_phase
- XX endif
- XX
- XXxfer_error: mov al,CERROR ;Command Failed with Bad Status
- XX jmp short docmd_exit
- XXxfer_offline: mov al,COFFLINE ;Unit went OffLine
- XX jmp short docmd_exit
- XXxfer_parerr: mov al,CPARERR ;Parity Error Detected
- XX jmp short docmd_exit
- XXxfer_selerr: mov al,CSELERR ;Re-Select?
- XX
- XXdocmd_exit: mov docmd_estatus,al
- XX mov byte ptr es:[si],CMDBASE
- XX pop es
- XX popa
- XX mov al,docmd_estatus
- XX cmp al,COK
- XX jz docmd_exit_ok
- XX stc
- XXdocmd_exit_ok: ret
- XXdocmd endp
- XX
- XX;
- XX; Wait One Hundred Micros Seconds
- XX;
- XX; The value of 'cx' is computed for an 8 Mhz Clock
- XX;
- XXwait100us proc near
- XX push cx ; (3) = 375ns
- XX mov cx,79 ; (2) = 250ns
- XXwait_u_loop: loop wait_u_loop ; (10) = 1250ns * X
- XX pop cx ; (5) = 625ns
- XX ret ; (11+) = 1375ns
- XXwait100us endp
- XX
- XX;
- XX; Monitor the Bus Phase on the Video Screen
- XX;
- XX if monitor
- XXshow_phase proc
- XX push es
- XX push di
- XX or ax,VIDEO_COLOR
- XX mov di,VIDEO_SEG
- XX mov es,di
- XX mov di,VIDEO_OFS
- XX stosw
- XX pop di
- XX pop es
- XX ret
- XXshow_phase endp
- XX endif
- SHAR_EOF
- if test 22277 -ne "`wc -c < 'subs.asm'`"
- then
- echo shar: error transmitting "'subs.asm'" '(should have been 22277 characters)'
- fi
- fi # end of overwriting check
- echo shar: extracting "'units.asm'" '(3996 characters)'
- if test -f 'units.asm'
- then
- echo shar: will not over-write existing file "'units.asm'"
- else
- sed 's/^XX//' > 'units.asm' << \SHAR_EOF
- XX;
- XX; target information/control structures
- XX;
- XX even
- XXunit0 db size unit dup (-1)
- XX even
- XXunit1 db size unit dup (-1)
- XX even
- XXunit2 db size unit dup (-1)
- XX even
- XXunit3 db size unit dup (-1)
- XX even
- XXunit4 db size unit dup (-1)
- XX even
- XXunit5 db size unit dup (-1)
- XX even
- XXunit6 db size unit dup (-1)
- XX ife reserve_addr
- XX even
- XXunit7 db size unit dup (-1)
- XX endif
- XX
- XX;
- XX; basic BPB array
- XX;
- XX even
- XXbpb0 db size bpb dup (-1)
- XX even
- XXbpb1 db size bpb dup (-1)
- XX even
- XXbpb2 db size bpb dup (-1)
- XX even
- XXbpb3 db size bpb dup (-1)
- XX even
- XXbpb4 db size bpb dup (-1)
- XX even
- XXbpb5 db size bpb dup (-1)
- XX even
- XXbpb6 db size bpb dup (-1)
- XX even
- XXbpb7 db size bpb dup (-1)
- XX
- XX;
- XX; Additional entries if needed
- XX;
- XX ife large_drives
- XX even
- XXbpb8 db size bpb dup (-1)
- XX even
- XXbpb9 db size bpb dup (-1)
- XX even
- XXbpbA db size bpb dup (-1)
- XX even
- XXbpbB db size bpb dup (-1)
- XX even
- XXbpbC db size bpb dup (-1)
- XX even
- XXbpbD db size bpb dup (-1)
- XX even
- XXbpbE db size bpb dup (-1)
- XX even
- XXbpbF db size bpb dup (-1)
- XX endif
- XX
- XX even
- XXunit_array dw unit0
- XX dw unit1
- XX dw unit2
- XX dw unit3
- XX dw unit4
- XX dw unit5
- XX dw unit6
- XX ife reserve_addr
- XX dw unit7
- XX endif
- XX
- XX even
- XXbpb_array dw bpb0 ;BPB Array for DOS
- XX dw bpb1
- XX dw bpb2
- XX dw bpb3
- XX dw bpb4
- XX dw bpb5
- XX dw bpb6
- XX dw bpb7
- XX ife large_drives
- XX dw bpb8
- XX dw bpb9
- XX dw bpbA
- XX dw bpbB
- XX dw bpbC
- XX dw bpbD
- XX dw bpbE
- XX dw bpbF
- XX endif
- XXbpb_hw_mark dw bpb_array
- XX
- XXtape_unit dw -1
- XXcur_unit dw unit0
- XXcur_bpb dw bpb0
- XX
- XX;
- XX; Given the request header in es:bx
- XX; Return a pointer in ds:di to the unit entry
- XX; or 'C' if no such unit exists.
- XX;
- XX; Do not destroy es:bx !!!
- XX;
- XXfind_unit proc near
- XX pusha
- XX mov ah,es:[bx].rh_unit ;What drive did they want
- XX lea di,unit_array
- XX lea si,bpb_array
- XX mov cx,MAXUNIT ;How many to search
- XXfind_loop: mov bx,[di] ;Point at a unit
- XX mov al,[bx].unit_num_drv ;Does this SCSI device
- XX or al,al ;Have any Drives Defined?
- XX jz find_next
- XX mov dh,[bx].unit_1st_drv ;Get First Drive Number
- XXfind_unit_loop: cmp ah,dh ;Is this the correct drive?
- XX jz find_match
- XX inc si ;Bump to next BPB
- XX inc si
- XX ife large_drives
- XX inc dh ;Bump Drive Number
- XX dec al ;Dec Drive count
- XX jnz find_unit_loop ;Try next Drive
- XX endif
- XX jmp short find_next ;Try next SCSI device
- XXfind_match: mov cur_unit,bx ;Found a match
- XX mov ax,[si]
- XX mov cur_bpb,ax
- XX clc
- XX jmp find_exit
- XXfind_next: inc di
- XX inc di
- XX loop find_loop
- XX stc ;No More units, Error
- XXfind_exit: popa
- XX ret
- XXfind_unit endp
- XX
- XX;
- XX; Given the data in a unit entry,
- XX; create the bpb for the unit.
- XX;
- XXmake_bpb proc near
- XX mov di,cur_bpb ;Get the current BPB
- XX mov bx,cur_unit ;Get the current Unit
- XX;
- XX; First the basic stuff
- XX;
- XX mov [di].bpb_ss,P_SECT
- XX mov [di].bpb_au,CLUSTSIZE
- XX mov [di].bpb_rs,1
- XX mov [di].bpb_nf,2
- XX mov [di].bpb_de,512
- XX mov [di].bpb_st,SECT_TRACK
- XX mov [di].bpb_nh,1
- XX mov [di].bpb_hs_lsw,0
- XX mov [di].bpb_hs_msw,0
- XX mov [di].bpb_md,0F8h
- XX;
- XX; then the size and fat sectors
- XX;
- XX mov dh,[bx].unit_cap_buf.cap_sectors_b3
- XX mov dl,[bx].unit_cap_buf.cap_sectors_b2
- XX mov ah,[bx].unit_cap_buf.cap_sectors_b1
- XX mov al,[bx].unit_cap_buf.cap_sectors_b0
- XX if large_drives
- XX mov [di].bpb_ts,0 ;(32 bit size)
- XX and ax,ROUND_CYL ;Round to nearest Cyl
- XX mov [di].bpb_ts_lsw,ax
- XX mov [di].bpb_ts_msw,dx
- XX sub [di].bpb_ts_lsw,1 ;Make it zero relative
- XX sbb [di].bpb_ts_msw,0
- XX mov bx,P_SECT ;Figure out how many
- XX div bx ;sectors it will take
- XX mov dx,0 ;to hold the FAT for
- XX mov bx,CLUSTSIZE ;this drive.
- XX div bx
- XX mov dx,0
- XX mov bx,2
- XX mul bx
- XX else
- XX or dx,dx
- XX jz make_bpb_last ;Use up the last few sectors
- XX dec dx ;Use up 65536 Sectors
- XX mov [bx].unit_cap_buf.cap_sectors_b3,dh
- XX mov [bx].unit_cap_buf.cap_sectors_b2,dl
- XX mov dx,0 ;Max of 32 Meg
- XX mov ax,65535
- XX jmp short make_bpb_ts
- XXmake_bpb_last: mov [bx].unit_cap_buf.cap_sectors_b1,0
- XX mov [bx].unit_cap_buf.cap_sectors_b0,0
- XX and ax,ROUND_CYL ;Round to nearest Cyl
- XX dec ax ;Make it zero relative
- XXmake_bpb_ts: mov [di].bpb_ts,ax
- XX shr ax,SECT_2_FS
- XX endif
- XX inc ax ;Allow for round-off
- XX mov [di].bpb_fs,ax
- XX ret
- XXmake_bpb endp
- SHAR_EOF
- if test 3996 -ne "`wc -c < 'units.asm'`"
- then
- echo shar: error transmitting "'units.asm'" '(should have been 3996 characters)'
- fi
- fi # end of overwriting check
- #
- # End of shell archive
- #
- exit 0
- --
- Brian Antoine |
- ISC-Bunker Ramo | ...uunet!isc-br!tau-ceti!briana
- Spokane, WA | briana@tau-ceti.isc-br.com
-
- exit 0 # Just in case...
- --
- Kent Landfield INTERNET: kent@sparky.IMD.Sterling.COM
- Sterling Software, IMD UUCP: uunet!sparky!kent
- Phone: (402) 291-8300 FAX: (402) 291-4362
- Please send comp.sources.misc-related mail to kent@uunet.uu.net.
-